#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/init.h>
#include <linux/fs.h>
#include <linux/slab.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#include <linux/delay.h>
#include <linux/cdev.h>
#include <linux/device.h>
#include <linux/of.h>
#include <linux/of_address.h>
#include <linux/of_irq.h>

#define		DTS_LED_CNT		(1)
#define		DTS_LED_NAME	"dtsled"



//dtsled设备结构体
struct dtsled_dev
{
	dev_t 				devid;	//设备号
	int 				major;	//主设备号
	int 				minor;	//主设备号
	struct 	cdev 		cdev;	//字符设备
};

struct dtsled_dev dtsled;

static const struct  file_operations dtsled_fops =
{
	.owner = THIS_MODULE,
};	//dtsled 字符设备操作集

//////////////////////////////////////////////////////////////////
static int __init dtsled_init(void)
{
	int ret = 0;
	//申请设备号
	dtsled.major = 0;	//设备号由内核申请
	if(dtsled.major)	//定义了设备号
	{
		dtsled.devid = MKDEV(dtsled.major,0);
		ret = register_chrdev_region(dtsled.devid,DTS_LED_CNT,DTS_LED_NAME);
	}
	else	//申请设备号
	{
		ret = alloc_chrdev_region(&dtsled.devid,0,DTS_LED_CNT,DTS_LED_NAME);
		dtsled.major = MAJOR(dtsled.devid);
		dtsled.minor = MINOR(dtsled.devid);
	}
	if (ret < 0)
	{
		goto fail_devid;
	}
	//注册字符设备
	dtsled.cdev.owner = THIS_MODULE;
	cdev_init(&dtsled.cdev,&dtsled_fops);
	ret = cdev_add(&dtsled.cdev,dtsled.devid,DTS_LED_CNT);
	if(ret < 0)
	{
		goto fail_cdev;
	}
	//3自动创建设备节点
	return 0;
fail_cdev:
	unregister_chrdev_region(dtsled.devid,DTS_LED_CNT);
fail_devid:
	return ret;
}

//模块出口
static void __exit dtsled_exit(void)
{
	//删除设备
	cdev_del(&dtsled.cdev);
	//释放设备号
	unregister_chrdev_region(dtsled.devid,DTS_LED_CNT);
}

/*模块入口*/
module_init(dtsled_init);
/*模块出口*/
module_exit(dtsled_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("Eason");
